﻿using System;
using System.Xml;

namespace PstBakup2013Server
{
    internal class PstFile : IEquatable<PstFile>
    {
        internal string LocalPath { get; set; }
        internal string RemotePath { get; set; }
        internal bool IsSetToBackup { get; set; }
        internal bool IsScheduledForBackup { get; set; }
        internal bool IsSavedAtLeastOnce { get; set; }
        internal DateTime LastDateSaved { get; set; }
        internal int ResultID { get; set; }
        internal long Size { get; set; }
        internal long CompressedSize { get; set; }
        internal bool IsCompressed { get; set; }
        internal string CompressionRate { get; set; }
        internal DateTime StartTime { get; set; }
        internal DateTime EndTime { get; set; }
        internal TimeSpan BackupDuration { get; set; }
        internal string BackupSpeed { get; set; }
        internal String ErrorMessage { get; set; }

        internal PstFile()
        {
            this.LocalPath = String.Empty;
            this.RemotePath = String.Empty;
            this.IsSetToBackup = true;
            this.IsScheduledForBackup = true;
            this.IsSavedAtLeastOnce = true;
            this.LastDateSaved = DateTime.Now;
            this.ResultID = 0;
            this.Size = 0;
            this.CompressedSize = 0;
            this.IsCompressed = true;
            this.CompressionRate = String.Empty;
            this.StartTime = DateTime.Now;
            this.EndTime = DateTime.Now;
            this.BackupDuration = new TimeSpan();
            this.BackupSpeed = String.Empty;
            this.ErrorMessage = String.Empty;
        }

        internal PstFile(XmlNode node)
            : this()
        {
            this.LocalPath = String.Empty;
            this.RemotePath = String.Empty;
            this.IsSetToBackup = true;
            this.IsScheduledForBackup = true;
            this.IsSavedAtLeastOnce = true;
            this.LastDateSaved = new DateTime();
            this.Size = 0;
            this.CompressedSize = 0;
            this.IsCompressed = true;
            this.CompressionRate = String.Empty;
            this.StartTime = new DateTime();
            this.EndTime = new DateTime();
            this.BackupDuration = new TimeSpan();
            this.BackupSpeed = String.Empty;
            this.ResultID = 0;
            this.ErrorMessage = String.Empty;

            try
            {
                this.LocalPath = node.SelectSingleNode("LocalPath").InnerText;
                this.RemotePath = node.SelectSingleNode("RemotePath").InnerText;
                this.IsSetToBackup = Convert.ToBoolean(node.SelectSingleNode("Backup").InnerText);
                this.IsScheduledForBackup = Convert.ToBoolean(node.SelectSingleNode("ScheduledForBackup").InnerText);
                this.ResultID = Convert.ToInt32(node.SelectSingleNode("Result").InnerText);
                this.Size = Convert.ToInt64(node.SelectSingleNode("Size").InnerText);
                this.CompressedSize = Convert.ToInt64(node.SelectSingleNode("CompressedSize").InnerText);
                this.IsCompressed = Convert.ToBoolean(node.SelectSingleNode("Compressed").InnerText);
                this.StartTime = Convert.ToDateTime(node.SelectSingleNode("StartTime").InnerText);
                this.EndTime = Convert.ToDateTime(node.SelectSingleNode("EndTime").InnerText);
                this.ErrorMessage = node.SelectSingleNode("ErrorMessage").InnerText;
            }
            catch (Exception) { }
        }

        internal string GetPropertiesValues()
        {
            Single rate = this.Size == 0 ? 0 : (1f - (float)this.CompressedSize / (float)this.Size) * 100;
            this.CompressionRate = rate == 0 ? String.Format("{0:0%}", rate) : String.Format("{0:##.##}%", rate);
            this.BackupDuration = this.EndTime.Subtract(this.StartTime);
            Double speed = this.BackupDuration.TotalSeconds != 0 ? (this.CompressedSize / 1024 / 1024 / this.BackupDuration.TotalSeconds) : 0;
            this.BackupSpeed = speed == 0 ? "0" : String.Format("{0:##.##}", speed);

            object[] values = new object[]
            {
                this.LocalPath,
                this.RemotePath,
                this.IsSetToBackup,
                this.IsScheduledForBackup,
                this.IsSavedAtLeastOnce,
                this.LastDateSaved,
                (int)((float)this.Size / 1024f/1024f),
                (int)((float)this.CompressedSize / 1024f/1024f),
                this.IsCompressed,
                this.CompressionRate,
                this.StartTime,
                this.EndTime,
                this.BackupDuration,
                this.BackupSpeed,
                this.ResultID,
                this.ErrorMessage
            };

            return String.Format("{0};{1};{2};{3};{4};{5};{6:0,0};{7:0,0};{8};{9};{10};{11};{12};{13:#.##};{14};{15}", values);
        }

        /// <summary>
        /// Compare two instances of a <see cref="PstFile"/> to see if they reference the same local Pst file.
        /// </summary>
        /// <param name="other">The second <see cref="PstFile"/> to compare with.</param>
        /// <returns>True if the second <see cref="PstFile"/> refere to the same Pst file than the first <see cref="PstFile"/></returns>
        public bool Equals(PstFile other)
        {
            return (String.Compare(this.LocalPath, other.LocalPath, true) == 0);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return base.Equals(obj);

            if (!(obj is PstFile))
                throw new InvalidCastException("The 'obj' argument is not a PstFile object.");
            else
                return Equals(obj as PstFile);
        }

        public override int GetHashCode()
        {
            return this.LocalPath.GetHashCode();
        }

        public static bool operator ==(PstFile pstFile1, PstFile pstFile2)
        {
            return pstFile1.Equals(pstFile2);
        }

        public static bool operator !=(PstFile pstFile1, PstFile pstFile2)
        {
            return (!pstFile1.Equals(pstFile2));
        }

    }
}
